如果今天網站需要處理日期&時間的計算、顯示、比較等行為,你會想到什麼工具呢?
許多人看到「日期」、「時間」就直覺想到的是 new Date()
,畢竟這是原生的 API 嘛~但如果真的試著用原生的 Date 來操作,不免在很多時候會感受到無力與困惑,往往還是會需要透過第三方的 library 來協助。
而今天的主角 Day.js 就會是這方面的佼佼者!其他當然還有許多 libraries(如: Luxon、Date-fns),讓我們來看看為什麼只要牽涉到時間,大家就轉而選擇第三方套件吧!
如果考慮使用原生的 Date 來處理日期與時間,面對官方琳瑯滿目的 API,初學者可能會有以下疑惑:
.getYear()
、.getFullYear()
與.getUTCFullYear()
都是「年」差在哪?
為什麼.getMonth()
的一月是從 0 開始?.toISOString()
、.toUTCString()
、.toLocaleString()
要顯示時間該用哪個?
另外,可能有些邏輯要用很複雜的方式做到,比如:
以及,因為 Date 的 API 具有 mutable 的特性,也就是說會直接修改到 Date 物件本身,而不是回傳一個全新的物件。因此對於一些 set 系列的 API,這個特性如果沒有特別注意,就很容易產生 bug。
Day.js 是一個專門用來處理日期與時間的 library,官方網站直接寫:
Fast 2kB alternative to Moment.js with the same modern API
裡面提到了另一個 library 叫做 Moment.js,可以簡單理解為「mutable 版本的 Day.js」,也算是上個時代用來處理日期時間的熱門 library,但因為目前已經算是 deprecated 狀態,因此這邊就不特別說明它了。
Day.js 主打的是以下特點:
Day.js 在做的事情,其實很像 jQuery 的概念,也就是說「原生的操作很困難,所以引用簡單易懂的 library 來處理」,因此 Day.js 提供了一系列方便的 API,比如:
// 顯示指定日期格式
dayjs('2022-09-25').format('YYYY/MM/DD') // 2022/09/25
// 加減日期
dayjs('2022-09-25').add(3, 'day').format('YYYY/MM/DD') // 2022/09/28
// 比較日期
dayjs('2022-09-25').isBefore(dayjs('2022-09-26')) // true
比如 Moment.js,因為 API 屬於 mutable 特性,會遇到這樣的問題:
const today = moment('2022-09-25');
const tomorrow = today.add(1, 'day');
// today 居然也變成 26 號了!
console.log(today.format('YYYY-MM-DD')); // 2022-09-26
console.log(tomorrow.format('YYYY-MM-DD')); // 2022-09-26
往往需要透過手動 .clone()
來避免,但這其實在效能方便是比較不好的:
const today = moment('2022-09-25');
const tomorrow = today.clone().add(1, 'day');
// today 正常了! 但 .clone() 操作是比較昂貴的
console.log(today.format('YYYY-MM-DD')); // 2022-09-25
console.log(tomorrow.format('YYYY-MM-DD')); // 2022-09-26
因此 Day.js 將 API 改為 immutable,可以省掉不少麻煩(而且跟 Moment.js 的語法幾乎沒變):
const today = dayjs('2022-09-25');
const tomorrow = today.add(1, 'day');
console.log(today.format('YYYY-MM-DD')); // 2022-09-25
console.log(tomorrow.format('YYYY-MM-DD')); // 2022-09-26
從 Moment.js 這種 mutable API library 轉過來 Day.js,基本上可說是無痛轉移了,只有部分 plugin 需要手動 extend,以及需要轉換成 immutable API 的思維,其實是找不太到明顯的缺點。
由於是專門針對特定需求(日期與時間操作),因此這類 library 很明確,有需要就用XD
不像 jQuery 在當時是一黨獨大,Day.js 之外仍有很多可替換的操作日期 library,雖然各有不同特色,但目的是一致的,都是為了減少操作日期時間的困難度,讓使用者更方便,並寫出更好讀的 code。
由於公司的專案就是從使用 Moment.js 開始,我先是嘗到了一波甜頭
啊~原來操作日期可以這麼簡單!
但隨著商業需求日趨複雜,開始遇到了一些 bug,找到最後才發現原來是因為 Moment.js API 帶有 mutable 的特性,如果沒有特別注意就會寫出有 bug 的程式。
於是到下一個新專案後開始轉成 Day.js,狀況才好轉不少,比較少遇到意料之外的狀況。
How to work with date in plain JavaScript
老项目使用 dayjs 替代 moment 的注意事项